package org.footballmanager.pandafootball.system.controller;

import lombok.extern.slf4j.Slf4j;
import org.footballmanager.pandafootball.common.annotation.SystemControllerLog;
import org.footballmanager.pandafootball.common.constants.Constants;
import org.footballmanager.pandafootball.common.util.MD5Encoder;
import org.footballmanager.pandafootball.common.util.MakeCookie;
import org.footballmanager.pandafootball.common.util.RandomNumber;
import org.footballmanager.pandafootball.common.util.VerifyCodeUtil;
import org.footballmanager.pandafootball.system.domain.*;
import org.footballmanager.pandafootball.system.domain.enums.QX;
import org.footballmanager.pandafootball.system.service.*;
import org.footballmanager.pandafootball.system.service.impl.RedisService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.StringUtils;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;

import javax.imageio.ImageIO;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Slf4j
@Controller
public class UserLoginController {
    private static final String EMAIL = "email";
    private static final String NAME = "name";
    private static final String LOGINPAGE = "main/login";
    private static final String REGISTPAGE = "main/regist";
    private static final String FORGETPAGE = "main/forgetpwd";
    private static final String FORGETPAGE2 = "main/forgetpwd2";
    private static final String REDIRECTINDEX = "redirect:/index";
    private static final String REDIRECTLOGIN = "redirect:/login";
    private static final String CODE = "validateCodeRecruit";

    @Autowired
    private FootUserService footUserService;
    @Autowired
    private FootYysService footYysService;
    @Autowired
    private FootTeamService footTeamService;
    @Autowired
    private FootClubService footClubService;
    @Autowired
    private FootSjService footSjService;
    @Autowired
    private FootZnxService footZnxService;
    @Autowired
    private FootLyService footLyService;
    @Autowired
    private FootQdService footQdService;
    @Autowired
    private FootGpService footGpService;
    @Autowired
    private FootBfinfoService footBfinfoService;
    @Autowired
    private FootScinfoService footScinfoService;
    @Autowired
    private FootSociatyService footSociatyService;
    @Autowired
    private FootPersonService footPersonService;
    @Autowired
    private PhotoService photoService;
    @Autowired
    private FootXfService footXfService;
    @Autowired
    private RedisService redisService;
    @Autowired
    private FootBfDetailService footBfDetailService;
    @Autowired
    private FootBfMvpService footBfMvpService;
    @Autowired
    private FootTaxService footTaxService;

    @ModelAttribute
    public void init1(Model map) {
        map.addAttribute("userList", footUserService.getall());
        map.addAttribute("clubList", footClubService.getall());
        map.addAttribute("qdList", footQdService.getall());
        map.addAttribute("qyList", footPersonService.getall());
        map.addAttribute("sjList", footSjService.getall());
    }

    @RequestMapping(value = "/login", method = RequestMethod.GET)
    public String login(Model map, HttpServletRequest request) {
        request.getSession().setAttribute("title", redisService.get("title"));
        map.addAttribute(Constants.USER, new FootUser());
        map.addAttribute(Constants.YQTS, RandomNumber.randomContent(redisService));
        return LOGINPAGE;
    }

    @RequestMapping(value = "/login", method = RequestMethod.POST)
    public String loginPost(Model map, @Valid @ModelAttribute FootUser footUser,
                            BindingResult bindingResult, HttpServletRequest request, HttpServletResponse response, String rememberme) {
        FootUser user = footUserService.findUserByName(footUser.getName());
        boolean processLoginError = processLoginError(map, bindingResult, footUser, user, request);
        boolean processYzmError = processYzmError(map, bindingResult, footUser, request);
        if (!processLoginError || !processYzmError) {
            return LOGINPAGE;
        }
        user.setZhdlsj(new Date());
        user.setIp(request.getRemoteAddr());
        footUserService.updateAll(user, request);
        processLoginSession(request, user, rememberme, footUser, response);
        return REDIRECTINDEX;
    }

    private void processLoginSession(HttpServletRequest request, FootUser user, String rememberme, @Valid FootUser footUser, HttpServletResponse response) {
        request.getSession().setAttribute(Constants.USER, user);
        if (null != rememberme && "1".equals(rememberme)) {
            MakeCookie.addCookie(response, "username", footUser.getName());
            MakeCookie.addCookie(response, "password", footUser.getPassword());
        }
        Long logo = footTeamService.getLogoByUserid(user.getId());
        if (null != logo) {
            Photo photo = photoService.get(logo);
            request.getSession().setAttribute(Constants.LOGO, photo.getUrl());
        }
        Long slt = footTeamService.getSltByUserid(user.getId());
        if (null != slt) {
            Photo photo = photoService.get(slt);
            request.getSession().setAttribute(Constants.SLT, photo.getUrl());
        }
        request.getSession().setAttribute("nowTime", new Date());
        request.getSession().setAttribute(Constants.USERID, user.getId());
    }

    private boolean processLoginError(Model map, BindingResult bindingResult, FootUser footUser, FootUser user, HttpServletRequest request) {
        if (request.getSession(true).isNew()) {
            return false;
        }
        //session不失效
//		req.getSession().setMaxInactiveInterval(-1)
        if (user == null) {
            bindingResult.rejectValue(NAME, Constants.MISFORMAT, "无此用户注册信息");
            map.addAttribute(Constants.YQTS, RandomNumber.randomContent(redisService));
            return false;
        }
        String pwd = MD5Encoder.strToMD5(footUser.getPassword());
        if (!user.getPassword().equals(pwd)) {
            bindingResult.rejectValue(NAME, Constants.MISFORMAT, "用户名或密码不对,请检查");
            map.addAttribute(Constants.YQTS, RandomNumber.randomContent(redisService));
            return false;
        }
        if (user.getSd()) {
            bindingResult.rejectValue(NAME, Constants.MISFORMAT, "账号被锁定,请联系GM");
            map.addAttribute(Constants.YQTS, RandomNumber.randomContent(redisService));
            return false;
        }
        if (!user.getEnabled()) {
            bindingResult.rejectValue(NAME, Constants.MISFORMAT, "账号没有被激活，请查看邮箱激活");
            map.addAttribute(Constants.YQTS, RandomNumber.randomContent(redisService));
            return false;
        }
        return true;
    }

    private boolean processYzmError(Model map, BindingResult bindingResult, FootUser footUser, HttpServletRequest request) {
        String code = request.getSession().getAttribute(CODE).toString();
        if (StringUtils.isEmpty(code) || StringUtils.isEmpty(footUser.getYzm())) {
            bindingResult.rejectValue(Constants.YZM, Constants.MISFORMAT, "验证码不能为空");
            map.addAttribute(Constants.YQTS, RandomNumber.randomContent(redisService));
            return false;
        }
        String validatorcode = footUser.getYzm().toLowerCase();
        if (!validatorcode.equals(code)) {
            bindingResult.rejectValue(Constants.YZM, Constants.MISFORMAT, "验证码出错");
            map.addAttribute(Constants.YQTS, RandomNumber.randomContent(redisService));
            return false;
        }
        return true;
    }

    /**
     * 图形验证码生成方法
     *
     * @param response 响应
     * @param request  请求
     * @throws IOException 异常
     */
    @RequestMapping("/verifyCode")
    public void verifyCode(HttpServletResponse response, HttpServletRequest request) throws IOException {
        //利用图片工具生成图片
        //第一个参数是生成的验证码，第二个参数是生成的图片
        Object[] objs = VerifyCodeUtil.createImage();
        //将验证码存入Session
        request.getSession().setAttribute(CODE, objs[0]);

        //将图片输出给浏览器
        BufferedImage image = (BufferedImage) objs[1];
        response.setContentType("image/png");
        OutputStream os = response.getOutputStream();
        ImageIO.write(image, "png", os);
    }

    @RequestMapping(value = "/regist", method = RequestMethod.GET)
    public String pageLoad(Model map) {
        map.addAttribute(Constants.USER, new FootUser());
        return REGISTPAGE;
    }

    @RequestMapping(value = "/regist", method = RequestMethod.POST)
    public String regist(@Valid @ModelAttribute FootUser footUser, BindingResult bindingResult,
                         HttpServletRequest request) {
        String code = String.valueOf(request.getSession().getAttribute(CODE));
        String validatorcode = footUser.getYzm().toLowerCase();
        if (!validatorcode.equals(code)) {
            bindingResult.rejectValue(Constants.YZM, Constants.MISFORMAT, "验证码出错");
        }
        FootUser user = footUserService.findUserByName(footUser.getName());
        if (user != null) {
            bindingResult.rejectValue(NAME, Constants.MISFORMAT, "此用户已注册,请更换用户名");
        }
        List<FootUser> userList = footUserService.findUsersByNike(footUser.getNike());
        if (user != null && !userList.isEmpty()) {
            bindingResult.rejectValue("nike", Constants.MISFORMAT, "此昵称已注册,请更换昵称");
        }
        if (bindingResult.hasErrors()) {
            return REGISTPAGE;
        }
        footUser.setJoins(true);
        footUser.setZhdlsj(new Date());
        footUser.setIp(request.getRemoteAddr());
        request.getSession().setAttribute(Constants.USER, footUser);
        if ("".equals(footUser.getGameId())) {
            bindingResult.rejectValue("gameId", Constants.MISFORMAT, "游戏ID不能为空");
            return REGISTPAGE;
        }
        footUserService.save(footUser, request);
        request.getSession().setAttribute(Constants.MSG, "1");
        return "mail/emailActive";
    }

    @RequestMapping(value = "/checkEmail")
    @ResponseBody
    public JsonReturn checkEmail(String email) {
        if (footUserService.checkEmail(email)) {
            return new JsonReturn(Constants.ERROR);
        }
        return new JsonReturn(Constants.OK);
    }

    @RequestMapping(value = "/index", method = RequestMethod.GET)
    public String index(Model map, HttpServletRequest request) {
        FootUser user = (FootUser) request.getSession().getAttribute(Constants.USER);
        processLy(map);
        request.getSession().setAttribute("sjInfo", footSjService.getRunningSj());
        //获取当前赛季信息
        if (!user.getQx().equals(QX.ADMIN) && !user.getQx().equals(QX.NORMAL)) {
            processScInfo(user, map);
            processOthers(user, map);
            return "main/index_hy";
        } else if (user.getQx().equals(QX.NORMAL)) {//一般用户
            processNormal(map, user);
            return "main/index_normal";
        } else {
            return "main/index_admin";
        }
    }

    private void processNormal(Model map, FootUser user) {
        map.addAttribute("yysList", footYysService.findYysTop10());
        //排位赛积分榜
        map.addAttribute("jfb", footYysService.getJfb());
        //已完成比赛信息
        map.addAttribute("yws", footBfinfoService.findYysByUserId(user.getId()));
    }

    private void processOthers(FootUser user, Model map) {
        //已完成比赛信息
        map.addAttribute("yws", footBfinfoService.getSubmitData(user.getId(), footSjService.getSj()));
        //挂牌球员信息
        map.addAttribute("gpList", footGpService.findGpNotSuccess());
        //解约球员信息
        map.addAttribute("xfList", footXfService.findXfByTimeDesc(user.getId()));
        // 根据用户的常规赛类别取当前常规赛的积分榜
        map.addAttribute("jfb", footClubService.getScoreboard(false, footSjService.getSj()));
        //排位赛TOP10
        map.addAttribute("yysList", footYysService.findYysTop10());
        //战队TOP10
        map.addAttribute("zdList", footSociatyService.findZdTop10());
        //射手榜
        map.addAttribute("ssbList", footBfDetailService.findJqTop10());
        //助攻榜
        map.addAttribute("zgbList", footBfDetailService.findZgTop10());
        //MVP榜
        map.addAttribute("mvpbList", footBfMvpService.findMvpTop10());
    }

    private void processScInfo(FootUser user, Model map) {
        //获取用户收藏信息
        List<FootScinfo> scList = footScinfoService.findCollectionByUserId(user.getId());
        if (scList != null && !scList.isEmpty()) {
            List<FootPerson> listperson = new ArrayList<>();
            for (FootScinfo sc : scList) {
                listperson.add(footPersonService.get(sc.getQyId()));
            }
            map.addAttribute("mysc", listperson);
        }
    }

    private void processLy(Model map) {
        //公告板
        List<FootLy> lylist = footLyService.findLyBySendtimeDesc();
        if (lylist.size() > 5) {
            map.addAttribute("lyList", lylist.subList(0, 5));
        } else {
            map.addAttribute("lyList", lylist);
        }
    }

    @RequestMapping(value = "/logout", method = RequestMethod.GET)
    public String logout(HttpServletRequest request) {
        request.getSession().removeAttribute(NAME);
        return REDIRECTLOGIN;
    }

    @RequestMapping(value = "/forgetpwd", method = RequestMethod.GET)
    public String forgetpwd(Model map) {
        map.addAttribute(Constants.USER, new FootUser());
        return FORGETPAGE;
    }

    @RequestMapping(value = "/forgetpwd", method = RequestMethod.POST)
    public String forgetpwd(@ModelAttribute FootUser footUser, BindingResult bindingResult,
                            Model map, @RequestParam Integer method, HttpServletRequest request) {
        String result = processForgetPwdError(footUser, method, bindingResult);
        if (!result.equals(Constants.OK)) {
            return result;
        }
        FootUser user = footUserService.findUserByNameEmail(footUser.getName(), footUser.getEmail());
        if (user == null) {
            bindingResult.rejectValue(EMAIL, Constants.MISFORMAT, "该用户或电子邮件未注册!");
            return FORGETPAGE;
        }
        if (method.equals(1)) {
            if (StringUtils.isEmpty(user.getQes1()) || StringUtils.isEmpty(user.getQes2())) {
                bindingResult.rejectValue(NAME, Constants.MISFORMAT, "该用户未设置密码找回!");
                return FORGETPAGE;
            }
            map.addAttribute(Constants.USER, user);
            return FORGETPAGE2;
        } else {
            footUserService.changePassword(user, request, map, true);
            return "mail/emailActive";
        }
    }

    private String processForgetPwdError(FootUser footUser, Integer method, BindingResult bindingResult) {
        if (StringUtils.isEmpty(footUser.getEmail())) {
            bindingResult.rejectValue(EMAIL, Constants.MISFORMAT, "电子邮件不能为空");
            return FORGETPAGE;
        }
        if (StringUtils.isEmpty(footUser.getName())) {
            bindingResult.rejectValue(NAME, Constants.MISFORMAT, "用户名不能为空");
            return FORGETPAGE;
        }
        if (method == null) {
            bindingResult.rejectValue(NAME, Constants.MISFORMAT, "请选择一种密码找回方式");
            return FORGETPAGE;
        }
        return Constants.OK;
    }

    @RequestMapping(value = "/forgetpwd2", method = RequestMethod.POST)
    public String forgetpwd2(@ModelAttribute FootUser footUser, BindingResult bindingResult,
                             HttpServletRequest request, Model map) {
        FootUser user = footUserService.get(footUser.getId());
        if (StringUtils.isEmpty(footUser.getAns1()) || StringUtils.isEmpty(footUser.getAns2())) {
            bindingResult.rejectValue("ans1", Constants.MISFORMAT, "请输入答案");
            return FORGETPAGE2;
        }
        if (!user.getAns1().equals(footUser.getAns1())) {
            bindingResult.rejectValue("ans1", Constants.MISFORMAT, "问题回答错误");
            return FORGETPAGE2;
        } else if (!user.getAns2().equals(footUser.getAns2())) {
            bindingResult.rejectValue("ans2", Constants.MISFORMAT, "问题回答错误");
            return FORGETPAGE2;
        }
        String newPassword = footUserService.changePassword(user, request, map, false);
        map.addAttribute("newPassword", newPassword);
        return "main/forgetpwd3";
    }

    @RequestMapping(value = "/getcookie", method = RequestMethod.POST)
    @ResponseBody
    public JsonReturn getcookie(HttpServletRequest request) {
        Cookie un = MakeCookie.getCookieByName(request, "username");
        Cookie pwd = MakeCookie.getCookieByName(request, "password");
        if (null != un && null != pwd) {
            FootUser user = new FootUser();
            user.setName(un.getValue());
            user.setPassword(pwd.getValue());
            return new JsonReturn(Constants.OK, user);
        } else {
            return new JsonReturn(Constants.ERROR);
        }
    }

    @RequestMapping(value = "/deleteznx", method = RequestMethod.GET)
    public String deleteznx(@RequestParam Long id, HttpServletRequest request) {
        footZnxService.delete(id, request);
        return REDIRECTINDEX;
    }

    @RequestMapping(value = "/help", method = RequestMethod.GET)
    public String help() {
        return "help/help";
    }

    /**
     * 邮箱激活
     *
     * @param id      用户主键
     * @param request 请求
     * @param map     参数
     * @return 页面
     */
    @RequestMapping(value = "/emailActivate", method = RequestMethod.GET)
    @SystemControllerLog(description = "激活邮箱")
    public String emailActivate(@RequestParam Long id, HttpServletRequest request, Model map) {
        FootUser user = footUserService.get(id);
        if (user == null) {
            map.addAttribute(Constants.MSG, "用户不存在");
            return "mail/emailActivateFailure";
        }
        if (user.getEnabled()) {
            map.addAttribute(Constants.MSG, "用户已激活账号，不能重复激活");
            return "mail/emailActivateFailure";
        }
        //处理邮件激活
        footUserService.setEnabledTrue(user, request);
        return REDIRECTINDEX;
    }

}
